// config.get() and config.set() store config data in (near-)json in prefs.js.
var none = { players: {}, cities: {}, islands: {} };

var data = eval(GM_getValue("config", {}) || {});
var server = eval(GM_getValue(location.host, none) || none);

function saveServer() {
	GM_setValue(location.host, uneval(server).replace(/ \(void 0\)/g, ""));
}

var config = (function() {
	function get(name, value) {
	try {
		if (arguments.length < 2) value = optionDefault(name);
		return data.hasOwnProperty(name) ? data[name] : value;
		} catch(e) {
			console.log("config.get("+ arguments.length +": "+ name +", "+ value);
			throw(e);
		}
	}

	function make(getOrSet, what, dflt) {
		return function(name, value, id) {
			return getOrSet([what, id || dflt()].concat(array(name)), value);
		};
	}

	var getCity = make(getServer, "cities", mainviewCityID);
	var setCity = make(setServer, "cities", mainviewCityID);
	var getIsle = make(getServer, "islands", islandID);
	var setIsle = make(setServer, "islands", islandID);

	function getServer(name, value) {
		if ("?!" == value) console.log(name, value);
		var path = isString(name) ? name.split(".") : name;
		var save = name;
		var scope = server;
		for (var i = 0; i < path.length; i++) {
			name = path[i];
			if (!scope.hasOwnProperty(name)) {
				if ("?!" == value) console.log(save.join("/"), scope);
				return value;
			}
			scope = scope[name];
		}
		if ("?!" == value) console.log(save.join("-"), scope);
		return scope;
	}

	function set(name, value) {
		var path = isString(name) ? name.split(".") : name;
		var scope = data, last = path.length - 1;
		for (var i = 0; i <= last; i++) {
			name = path[i];
			if (i != last)
				scope = scope[name] = scope[name] || {};
			else
				scope[name] = value;
		}
		expensive(saveConfig)();
		return value;
	}

	function setServer(name, value) {
		var path = isString(name) ? name.split(".") : name;
		var tmpl = { 3: { cities: [{}, {l: Array, p: Array, q: Array}] } };
		var scope = server, last = path.length - 1;
		for (var i = 0; i <= last; i++) {
			name = path[i];
			if (i != last) {
				if (!scope.hasOwnProperty(name)) try {
					var type = tmpl[path[0]][path.length][i][name];
				} catch(e) { type = Object; } finally {
					scope[name] = new type;
				}
				scope = scope[name];
			} else
				scope[name] = value;
		}
		expensive(saveServer)();
		return value;
	}

	function remCity(name) {
		return remServer(name +":"+ cityID());
	}

	function remIsle(name) {
		return remServer(name +"/"+ islandID());
	}

	function remServer(name) {
		return remove(name +":"+ location.hostname);
	}

	function keys(re) {
		re = re || /./;
		var list = [];
		for (var id in data)
			if (data.hasOwnProperty(id) && re.test(id))
				list.push(id);
		return list;
	}

	function remove(id) {
		if (/function|object/.test(typeof id)) {
			var value = [], re = id;
			for (id in data)
				if (data.hasOwnProperty(id) && id.test(re)) {
					value.push(data[id]);
					delete data[id];
				}
		} else {
			value = data[id];
			delete data[id];
		}
		expensive(saveConfig)();
		return value;
	}

	return { get:get, set:set, remove:remove, keys:keys,
	         setCity:setCity, getCity:getCity, remCity:remCity,
	         setIsle:setIsle, getIsle:getIsle, remIsle:remIsle,
	         setServer:setServer, getServer:getServer, remServer:remServer };
})();

// buildings:
var buildingIDs = {
	townHall: 0, townhall: 0, port: 3, academy: 4, shipyard: 5, barracks: 6,
	warehouse: 7, wall: 8, tavern: 9, museum: 10, palace: 11, embassy: 12,
	branchOffice: 13, workshop: 15, "workshop-army": 15, "workshop-fleet": 15,
	safehouse: 16, palaceColony: 17, resource: 1, tradegood: 2
};

function cityID() {
	var id = urlParse("cityId") || urlParse("id");
	var view = urlParse("view");
	if (id)
		if (buildingIDs.hasOwnProperty(view) && !urlParse("type") || { city:1 }[view])
			return integer(id);
	var a = $X('//li[@class="viewCity"]//a');
	return a && integer(urlParse("id", a.search));
}

function mainviewCityID() {
	var city = $X('id("breadcrumbs")/a[@class="city"]');
	if (city) return integer(urlParse("id", city.search));
	if ({ island: 1, resource: 1, tradegood: 1 }[document.body.id])
		return cityID();
	if ((city = urlParse("id", $X('id("advCities")//a').search)))
		return integer(city);
	return cityID();
}

function islandID(city) {
	return urlParse("id", $X('//li[@class="viewIsland"]//a').search);
}

function url(query) {
	return (location.search || "").replace(/([#?].*)?$/, query||"");
}

function urlTo(what, id, opts) {
	if (isUndefined(opts)) opts = {};
	switch (what) {
		case "message":
			var from = opts && opts.from || cityID();
			return url("?view=sendMessage&with="+ from +"&destinationCityId="+ id +"&oldView=island");
			
		case "island":
			var city = "";
			if (isObject(id)) {
				if ((city = id.city)) {
					if (!id.island && !(id.island = config.getCity("i", 0, city)))
						return "#";
					city = "&selectCity="+ city;
				}
				id = id.island;
			}
			return url("?view=island&id="+ id + city);
	}
}

function sort(col) {
	function sortTable(a, b) {
		var a = a.cells[col-1].textContent;
		var b = b.cells[col-1].textContent;
		return (a < b) ? -1 : ((a > b) ? 1 : 0);
	}
	
	function moveRows(body, newRows) {
		for (var i = 0; i < newRows.length; i++) {
			body.appendChild(newRows[i]); 
		}
	}

	var body = $X('//table[@id="ot-3"]/tbody');
	var rows = $x('tr[@class="ot-row"]', body);
	var newRows = new Array();
	for (var i = 0; i < rows.length; i++) { 
		newRows[i] = rows[i]; 
	}

	newRows.sort(sortTable);
	moveRows(body, newRows);
}
